/*** Created Time: 2022年5月24日 16:17:50 ***/
/*** Author: Eric                        ***/

// 从用户态到内核态的系统调用

#include <onix/interrupt.h>
#include <onix/assert.h>
#include <onix/debug.h>
#include <onix/syscall.h>
#include <onix/task.h>
#include <onix/console.h>
#include <onix/memory.h>

#define     LOGK(fmt, args...)      DEBUGK(fmt, ##args)

#define     SYSCALL_SIZE            (256)  // 系统调用函数表的大小

handler_t syscall_table[SYSCALL_SIZE];     // 系统调用函数表

void syscall_check(u32 nr)
{
    if(nr >= SYSCALL_SIZE) {
        // 如果系统调用号大于等于SYSCALL_SIZE，报错
        panic("syscall nr error!!!");
    }
}

static void sys_default(void)
{
    panic("syscall not implemented!!!");
}

static u32 sys_test(void)
{
    // LOGK("syscall test...\n");
    return 255;
}

int32 sys_write(fd_t fd, char *buf, u32 len)
{
    if (fd == stdout || fd == stderr)
    {
        return console_write(buf, len);
    }
    // todo
    panic("write!!!!");
    return 0;
}

// 在 clock.c 中实现
extern time_t sys_time(void);

void syscall_init(void)
{
    for(size_t i=0; i<SYSCALL_SIZE; i++) {
        syscall_table[i] = sys_default;
    }

    syscall_table[SYS_NR_TEST] = sys_test;
    syscall_table[SYS_NR_EXIT] = task_exit;
    syscall_table[SYS_NR_FORK] = task_fork;
    syscall_table[SYS_NR_WAITPID] = task_waitpid;
    syscall_table[SYS_NR_SLEEP] = task_sleep;
    syscall_table[SYS_NR_YIELD] = task_yield;

    syscall_table[SYS_NR_GETPID] = sys_getpid;
    syscall_table[SYS_NR_GETPPID] = sys_getppid;

    syscall_table[SYS_NR_BRK] = sys_brk;

    syscall_table[SYS_NR_WRITE] = sys_write;

    syscall_table[SYS_NR_TIME] = sys_time;
}